#!/usr/bin/env python3

"""test linear model with relative error
esp. symmetric percentage error
"""

import numpy as np
import pandas as pd
import mo
from sklearn.linear_model import *
from sklearn.ensemble import GradientBoostingRegressor, AdaBoostRegressor
from sklearn.neural_network import MLPRegressor
from sklearn.gaussian_process import GaussianProcessRegressor
from sklearn.gaussian_process.kernels import *
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import PolynomialFeatures, FunctionTransformer
from sklearn.decomposition import PCA, KernelPCA, FastICA
from sklearn.kernel_ridge import KernelRidge
from sklearn.model_selection import GridSearchCV
from sklearn.svm import LinearSVR, SVR
from sklearn.model_selection import *

from utils import *
from relinear import *

#errors
e = relative_errors['symmetric percentage error']


models={
    'SMPE-Linear': SMPERegressor(),
    'Linear': Max0LinearRegression(),
    'Ridge': maxo(Ridge)(),
    'Bayesian': maxo(BayesianRidge)(),
    'Huber': maxo(HuberRegressor)(),
    # 'Theil-Sen': maxo(TheilSenRegressor)(),
    # 'LinearSVR': maxo(LinearSVR)(),
    # 'Gaussian': GaussianProcessRegressor(),
    'Log-SMPE-Linear': SMPELogRegressor(),
    'Log-Linear': LogLinearRegression(),
    'Log-Ridge': logarithm(Ridge)(),
    'Log-Bayesian': logarithm(BayesianRidge)(),
    'Log-Huber': logarithm(HuberRegressor)(),
    # 'Log-Theil-Sen': logarithm(TheilSenRegressor)(),
    # 'LogRANSAC': logarithm(RANSACRegressor)(),
    # 'LogLinearSVR': logarithm(LinearSVR)(),
}

# data

FILENAME = 'data-diff003.csv'

data = pd.read_csv(FILENAME, index_col=0)
X_keys = ['RGB_R', 'RGB_G', 'RGB_B']
E_keys = ['e500(相对差)', 'e510(相对差)', 'e520(相对差)']
B_keys = ['b_500', 'b_510', 'b_520']
S_keys = ['s_500', 's_510', 's_520']


X = data[B_keys]
Y = data[S_keys]

print(f'''total number of data: {len(Y)}
size of test data: 0.2
''')

# test
import time
results = []
train_results = []
times = []
n_tests = 20
for i in range(1, n_tests+1):
    print(f'trial {i}/{n_tests}')
    _results = []
    _train_results = []
    _times = []
    X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.2)
    for mn, model in models.items():
        time1 = time.perf_counter()
        try:
            model.fit(X_train, Y_train)
        except:
            model = mo.MORegression(model=model)
            model.fit(X_train, Y_train)
        time2 = time.perf_counter()
        _times.append(time2 - time1)
        Y_pred = model.predict(X_test)
        E = np.mean(np.mean(e(Y_pred, Y_test)**2, axis=0))
        Y_fit = model.predict(X_train)
        Ef = np.mean(np.mean(e(Y_fit, Y_train)**2, axis=0))
        _results.append(E)
        _train_results.append(Ef)

    results.append(_results)
    train_results.append(_train_results)
    times.append(_times)


result = {}
result['测试误差'] = np.median(results, axis=0)
result['训练误差'] = np.median(train_results, axis=0)
result['训练耗时'] = np.median(times, axis=0)

result= pd.DataFrame(result, index=pd.Index(models.keys()))

print(result)
# result.to_csv('result-re.csv')
